// cf-212e
// 题意：给定n(<=5000)个点的树，现在要在这些点上修两种类型的饭店，
//       有一些要求：
//         1.每个点至多有一个饭店，且是两种类型之一的
//         2.每个类型的饭店都至少要有一个
//         3.相邻点不能是不同类型的饭店
//        现在问要使两种饭店的总数a+b最大，输出所有数目的方案(a, b)。
//
// 题解：这虽然是这场比赛的e题，但是这场比赛是反过来的，这是个500分的题。
//       只要在树上枚举每个分割点，然后背包就行。
//
// run: $exec < input
#include <iostream>
#include <vector>
#include <set>
#include <utility>

int const maxn = 5007;
int head[maxn], end_point[2 * maxn], next[2 * maxn];
int alloc = 2;
bool can[maxn];
int f[maxn][maxn];
int n, tick;

std::set<std::pair<int, int>> all;

void add_edge(int u, int v)
{
	end_point[alloc] = v; next[alloc] = head[u]; head[u] = alloc++;
	end_point[alloc] = u; next[alloc] = head[v]; head[v] = alloc++;
}

int dfs(int u, int parent)
{
	int tot = 0, ret = 1, sum = 0;
	std::vector<int> a;
	for (int p = head[u]; p; p = next[p]) {
		int v = end_point[p];
		if (v == parent) continue;
		a.push_back(dfs(v, u));
		sum += a[tot];
		ret += a[tot++];
	}
	a.push_back(n - 1 - sum);
	tot++;
	f[0][0] = ++tick;
	for (int i = 1; i <= tot; i++)
		for (int j = 0; j < n - 1; j++)
			if (f[i - 1][j] == tick) f[i][j] = tick;
			else if (j >= a[i - 1] && f[i - 1][j - a[i - 1]] == tick)
				f[i][j] = tick;
	for (int i = 1; i < n - 1; i++)
		if (f[tot][i] == tick) can[i] = true;
	return ret;
}

int main()
{
	std::ios::sync_with_stdio(false);
	std::cin >> n;
	for (int i = 1, x, y; i < n; i++) {
		std::cin >> x >> y;
		add_edge(x, y);
	}
	dfs(1, -1);
	for (int i = 1; i < n - 1; i++)
		if (can[i]) all.insert({i, n - 1 - i});
	std::cout << all.size() << '\n';
	for (auto i : all) std::cout << i.first << ' ' << i.second << '\n';
}

